/**
 * 统一认证和API通信服务
 * 集成认证、令牌管理和API请求功能
 */

class AuthService {
    /**
     * 初始化认证服务
     */
    constructor() {
        this.tokenKey = 'auth_token';
        this.userInfoKey = 'user_info';
        this.baseUrl = '';
        this.setupInterceptors();
    }

    /**
     * 设置请求拦截器，确保每个请求都附带JWT令牌
     */
    setupInterceptors() {
        // 拦截所有fetch请求
        const originalFetch = window.fetch;
        const self = this;
        
        window.fetch = function(url, options = {}) {
            // 获取令牌
            const token = self.getToken();
            
            // 如果有令牌，添加到请求头
            if (token) {
                // 确保headers对象存在
                options.headers = options.headers || {};
                
                // 添加Authorization头
                options.headers['Authorization'] = `Bearer ${token}`;
            }
            
            // 调用原始fetch
            return originalFetch(url, options)
                .then(response => {
                    // 处理401未授权错误
                    if (response.status === 401) {
                        // 清除令牌
                        self.removeToken();
                        
                        // 如果不是登录页面，重定向到登录页面
                        if (!window.location.pathname.includes('/login')) {
                            window.location.href = '/login?redirect=' + encodeURIComponent(window.location.pathname);
                        }
                    }
                    return response;
                });
        };
        
        // 拦截XMLHttpRequest请求
        const originalXHROpen = XMLHttpRequest.prototype.open;
        XMLHttpRequest.prototype.open = function() {
            const token = self.getToken();
            const originalSend = this.send;
            
            this.send = function() {
                if (token) {
                    this.setRequestHeader('Authorization', `Bearer ${token}`);
                }
                originalSend.apply(this, arguments);
            };
            
            originalXHROpen.apply(this, arguments);
        };
    }

    /**
     * 保存认证令牌到本地存储
     * @param {string} token JWT令牌
     */
    setToken(token) {
        if (token) {
            // 清理令牌格式
            token = this.cleanTokenFormat(token);
            localStorage.setItem(this.tokenKey, token);
        }
    }

    /**
     * 获取认证令牌
     * @returns {string|null} JWT令牌或null
     */
    getToken() {
        const token = localStorage.getItem(this.tokenKey);
        return token ? this.cleanTokenFormat(token) : null;
    }

    /**
     * 移除认证令牌
     */
    removeToken() {
        localStorage.removeItem(this.tokenKey);
        localStorage.removeItem(this.userInfoKey);
    }

    /**
     * 清理并验证令牌格式
     * @param {string} token - 待清理的令牌
     * @returns {string|null} 格式化后的令牌或null
     */
    cleanTokenFormat(token) {
        if (!token) {
            return null;
        }
        
        // 确保令牌是有效的格式
        token = token.trim();
        
        // 防止重复添加Bearer前缀
        if (token.startsWith('Bearer ')) {
            token = token.substring(7);
        }
        
        // 移除可能导致解析错误的字符
        token = token.replace(/[\r\n\t\s]/g, '');
        
        // 确保JWT格式正确（三部分，用点分隔）
        const parts = token.split('.');
        if (parts.length !== 3) {
            console.warn('令牌不是有效的JWT格式（缺少部分）');
            return null;
        }
        
        // 检查每个部分是否包含有效的Base64URL字符
        const validBase64Pattern = /^[A-Za-z0-9\-_=]+$/;
        for (let i = 0; i < parts.length; i++) {
            if (!validBase64Pattern.test(parts[i])) {
                console.warn(`令牌的第${i+1}部分包含非法Base64URL字符`);
                
                // 尝试清理非法字符（仅保留合法字符）
                parts[i] = parts[i].replace(/[^A-Za-z0-9\-_=]/g, '');
                
                // 如果清理后为空，则令牌无效
                if (!parts[i]) {
                    console.error('清理后的令牌部分为空，无法修复');
                    return null;
                }
            }
        }
        
        // 重新组合清理后的令牌
        return parts.join('.');
    }

    /**
     * 保存用户信息到本地存储
     * @param {Object} userInfo 用户信息
     */
    setUserInfo(userInfo) {
        if (userInfo) {
            localStorage.setItem(this.userInfoKey, JSON.stringify(userInfo));
        }
    }

    /**
     * 获取用户信息
     * @returns {Object|null} 用户信息或null
     */
    getUserInfo() {
        const userInfoStr = localStorage.getItem(this.userInfoKey);
        if (userInfoStr) {
            try {
                return JSON.parse(userInfoStr);
            } catch (e) {
                console.error('解析用户信息失败:', e);
                return null;
            }
        }
        return null;
    }

    /**
     * 用户登录
     * @param {string} username 用户名
     * @param {string} password 密码
     * @param {boolean} rememberMe 是否记住我
     * @returns {Promise<Object>} 登录结果
     */
    login(username, password, rememberMe = false) {
        return this.post('/api/auth/login', {
            username,
            password,
            rememberMe
        })
        .then(data => {
            if (data.code === 200 && data.data && data.data.token) {
                this.setToken(data.data.token);
                this.setUserInfo(data.data.userInfo);
                return data.data;
            } else {
                throw new Error(data.message || '登录失败');
            }
        });
    }

    /**
     * 用户登出
     * @returns {Promise<Object>} 登出结果
     */
    logout() {
        const token = this.getToken();
        this.removeToken();

        return this.post('/api/auth/logout')
        .catch(error => {
            console.error('登出请求失败:', error);
            // 即使请求失败，也清除了本地令牌
            return { code: 200, message: '已登出' };
        })
        .finally(() => {
            // 登出后重定向到登录页面
            window.location.href = '/login';
        });
    }

    /**
     * 检查用户是否已登录
     * @returns {boolean} 是否已登录
     */
    isAuthenticated() {
        return !!this.getToken();
    }

    /**
     * 刷新用户信息
     * @returns {Promise<Object>} 用户信息
     */
    refreshUserInfo() {
        const token = this.getToken();
        if (!token) {
            return Promise.reject(new Error('未登录'));
        }

        return this.get('/api/auth/user-info')
        .then(data => {
            if (data.code === 200) {
                this.setUserInfo(data.data);
                return data.data;
            } else {
                throw new Error(data.message || '获取用户信息失败');
            }
        });
    }

    /**
     * 发送GET请求
     * @param {string} url - 请求URL
     * @param {Object} params - 查询参数
     * @returns {Promise<any>} - 响应数据
     */
    async get(url, params = {}) {
        // 构建查询字符串
        const queryString = Object.keys(params)
            .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
            .join('&');
        
        // 构建完整URL
        const fullUrl = `${this.baseUrl}${url}${queryString ? `?${queryString}` : ''}`;
        
        try {
            // 发送请求
            const response = await fetch(fullUrl, {
                method: 'GET',
                credentials: 'same-origin'
            });
            
            // 解析响应
            return this.handleResponse(response);
        } catch (error) {
            console.error('API请求失败:', error);
            throw error;
        }
    }
    
    /**
     * 发送POST请求
     * @param {string} url - 请求URL
     * @param {Object} data - 请求数据
     * @returns {Promise<any>} - 响应数据
     */
    async post(url, data = {}) {
        try {
            // 发送请求
            const response = await fetch(`${this.baseUrl}${url}`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(data),
                credentials: 'same-origin'
            });
            
            // 解析响应
            return this.handleResponse(response);
        } catch (error) {
            console.error('API请求失败:', error);
            throw error;
        }
    }
    
    /**
     * 发送PUT请求
     * @param {string} url - 请求URL
     * @param {Object} data - 请求数据
     * @returns {Promise<any>} - 响应数据
     */
    async put(url, data = {}) {
        try {
            // 发送请求
            const response = await fetch(`${this.baseUrl}${url}`, {
                method: 'PUT',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(data),
                credentials: 'same-origin'
            });
            
            // 解析响应
            return this.handleResponse(response);
        } catch (error) {
            console.error('API请求失败:', error);
            throw error;
        }
    }
    
    /**
     * 发送DELETE请求
     * @param {string} url - 请求URL
     * @returns {Promise<any>} - 响应数据
     */
    async delete(url) {
        try {
            // 发送请求
            const response = await fetch(`${this.baseUrl}${url}`, {
                method: 'DELETE',
                credentials: 'same-origin'
            });
            
            // 解析响应
            return this.handleResponse(response);
        } catch (error) {
            console.error('API请求失败:', error);
            throw error;
        }
    }
    
    /**
     * 处理响应
     * @param {Response} response - Fetch API响应对象
     * @returns {Promise<any>} - 解析后的响应数据
     */
    async handleResponse(response) {
        // 尝试解析响应为JSON
        let data;
        try {
            data = await response.json();
        } catch (error) {
            throw new Error('无法解析响应数据');
        }
        
        // 如果响应不成功
        if (!response.ok) {
            // 抛出错误
            const error = new Error(data.message || '请求失败');
            error.status = response.status;
            error.data = data;
            throw error;
        }
        
        // 返回数据
        return data;
    }
}

// 创建全局认证服务实例
const authService = new AuthService();

// 添加全局辅助函数
window.login = (username, password, rememberMe) => authService.login(username, password, rememberMe);
window.logout = () => authService.logout();
window.isAuthenticated = () => authService.isAuthenticated();
window.refreshUserInfo = () => authService.refreshUserInfo();

// API快捷方法
window.api = {
    get: (url, params) => authService.get(url, params),
    post: (url, data) => authService.post(url, data),
    put: (url, data) => authService.put(url, data),
    delete: (url) => authService.delete(url)
};

// 页面加载时自动初始化
document.addEventListener('DOMContentLoaded', function() {
    // 拦截链接点击，确保带有JWT令牌
    document.addEventListener('click', function(event) {
        // 检查是否点击了链接
        if (event.target.tagName === 'A' && !event.target.hasAttribute('download') && 
            !event.target.getAttribute('href').startsWith('http') && 
            !event.target.getAttribute('href').startsWith('#')) {
            
            const token = authService.getToken();
            if (token) {
                // 阻止默认导航行为
                event.preventDefault();
                
                // 获取目标URL
                const href = event.target.getAttribute('href');
                
                // 创建表单进行导航（这样可以保持JWT头部）
                const form = document.createElement('form');
                form.method = 'GET';
                form.action = href;
                
                // 创建隐藏字段存储令牌
                const tokenInput = document.createElement('input');
                tokenInput.type = 'hidden';
                tokenInput.name = 'auth_token';
                tokenInput.value = token;
                
                form.appendChild(tokenInput);
                document.body.appendChild(form);
                form.submit();
            }
        }
    });
}); 